package island;

import java.awt.Color;
import java.awt.Graphics2D;

import main.Game;
import main.ImageParser;
import main.World;

import block.Block;


public class Island {

	public Block[][] blocks;
	private int vx, vy;
	private int x, y;
	private World world;
	
	//ATTENTION! -12<=v<=12 only
	public Island(int x, int y, int vx, int vy, World world, int width, int height)
	{
		blocks = Block.parse(generate(width, height));//(ImageParser.parse("resources/firstIsland.png"));
		this.x = x;
		this.y = y;
		this.vx = vx;
		this.vy = vy;	
		this.world = world;
		world.islands.add(this);
	}
	public Island(int x, int y, int vx, int vy, World world)
	{
		blocks = Block.parse((ImageParser.parse("resources/firstIsland.png")));
		this.x = x;
		this.y = y;
		this.vx = vx;
		this.vy = vy;	
		this.world = world;
		world.islands.add(this);
	}
	private byte[][] generate(int width, int height)
	{
		float caves, center_falloff, plateau_falloff, density;
	    byte[][] data = new byte[width][height];
	    for(int q=0;q<width;q++)
	    {
	    	for(int w=0;w<height;w++)
	    	{
	    		float xf = (float)q/(float)width;
	    		float yf = 1-(float)w/(float)height;
	    		
//	    		System.out.print(""+xf+" "+yf+" : ");
	    		
		        if(yf <= 0.8){
		            plateau_falloff = 1.0f;
		        }
		        else if(0.8 < yf && yf < 0.9)
		        {
		            plateau_falloff = (float) (1.0-(yf-0.8)*10.0);
		        }
		        else{
		            plateau_falloff = 0.0f;
		        }
		 
		        center_falloff = (float) (0.1f/(
		            Math.pow((xf-0.5)*1.5, 2)+
		            Math.pow((yf-1.0)*0.8, 2)
		        ));
		        
//		        caves = pow(simplex_noise(1, xf*5, yf*5, zf*5), 3);
//		        caves = (float) Math.pow(PerlinNoise.get2D(1, xf*5, yf*5), 3);
		        
//		        density = simplexNoise(50, xf, yf*0.5f);
		        density = PerlinNoise.noise2D(xf, yf);
		        density *= -100;
		        
		        density *=  center_falloff * plateau_falloff;
		        
//		        density *= (float) Math.pow(
//		            PerlinNoise.noise2D((xf+1)*3.0f, (yf+1)*3.0f)+0.4, 1.8
//		        );
		        
//		        System.out.print("|||"+density);
//		        if(caves>0.5){
//		            density = 0;
//		        }
		        
		        data[q][w] = (byte) (density>14 ? 3 : 0);
//		        System.out.print(density>500 ? "8" : " ");
	    	}
	    	System.out.println();
	    }
	    return data;
//	    float caves, center_falloff, plateau_falloff, density;
//	    byte[][] data = new byte[width][height];
//	    for(int q=0;q<width;q++)
//	    {
//	    	for(int w=0;w<height;w++)
//	    	{
//	    		float xf = (float)q/(float)width;
//	    		float yf = (float)w/(float)height;
//	    		
////	    		System.out.print(""+xf+" "+yf+" : ");
//	    		
//		        if(yf <= 0.8){
//		            plateau_falloff = 1.0f;
//		        }
//		        else if(0.8 < yf && yf < 0.9)
//		        {
//		            plateau_falloff = (float) (1.0-(yf-0.8)*10.0);
//		        }
//		        else{
//		            plateau_falloff = 0.0f;
//		        }
//		 
//		        center_falloff = (float) (0.1/(
//		            Math.pow((xf-0.5)*1.5, 2)+
//		            Math.pow((yf-1.0)*0.8, 2)
//		        ));
//		        
////		        caves = pow(simplex_noise(1, xf*5, yf*5, zf*5), 3);
////		        caves = (float) Math.pow(PerlinNoise.get2D(1, xf*5, yf*5), 3);
//		        
////		        density = simplexNoise(50, xf, yf*0.5f);
//		        density = PerlinNoise.get2D(3, xf, yf);
//		        density /= 100;
//		        
////		        density *=  center_falloff * plateau_falloff;
//		        
////		        density *= (float) Math.pow(
////		            PerlinNoise.noise2D((xf+1)*3.0f, (yf+1)*3.0f)+0.4, 1.8
////		        );
//		        
//		        System.out.print("|||"+density);
////		        if(caves>0.5){
////		            density = 0;
////		        }
//		        
//		        data[q][w] = (byte) (density>-1 ? 3 : 0);
////		        System.out.print(density>500 ? "8" : " ");
//	    	}
//	    	System.out.println();
//	    }
//	    return data;
	}
	
	private float simplexNoise(int octaves, float x, float y)
	{
	    float value = 0.0f;
	    for(int q=0; q < octaves; q++)
	    {
	        value += PerlinNoise.noise2D((float) (x*Math.pow(2, q)), (float) (y*Math.pow(2, q)));
	    }
	    return value;
	}
	
	public void tick()
	{
		addVelocity();
	}
	public void tickBlock(int x, int y)
	{
		Block block = blocks[x][y];
		if(block == null) return;
		blocks[x][y].tick();
		if(blocks[x][y].isDeleted())blocks[x][y] = null;
	}
	public void addVelocity()
	{		
		int block_size = world.BLOCK_SIZE;
		int steps=1;
		steps = (int) Math.ceil(Math.max(steps, Math.abs(vx/block_size)));
		steps = (int) Math.ceil(Math.max(steps, Math.abs(vy/block_size)));
		for(int w=0;w<steps;w++)
		{
			x += vx/steps;
	        y += vy/steps;		
//	        for(Island i2:World.islands)
//	        {
//	        	
//	        }
		}
	}
	public void draw(Graphics2D g)
	{
		int BLOCK_SIZE = world.BLOCK_SIZE;
		int x1 = Math.max(0, (int) ((Game.x-x)/BLOCK_SIZE));
		int x2 = Math.min(blocks.length, (int) ((Game.x+Game.WIDTH-x)/BLOCK_SIZE)+1);
		int y1 = Math.max(0, (int) ((Game.y-y) / BLOCK_SIZE));
		int y2 = Math.min(blocks[0].length, (int) ((Game.y+Game.HEIGHT-y) / BLOCK_SIZE)+1);		
		
    	for(int q=x1;q<x2;q++)
    	{
    		for(int w=y1;w<y2;w++)
    		{
    			Block block;
    			block = blocks[q][w];

    			if(block == null) continue;
    			g.setColor(block.getColor());
    			
    			g.fillRect((int)x+q*world.BLOCK_SIZE - Game.x, (int)y+w*world.BLOCK_SIZE - Game.y, world.BLOCK_SIZE, world.BLOCK_SIZE);
    		}
    	}
	}
	public static void collide(Island i1, Island i2)
	{
		
	}
	public long getX() {return x;}
	public long getY() {return y;}
	public long getVX() {return vx;}
	public long getVY() {return vy;}
	
}
